#include    "logger.h"
#include    "datetime.h"
#include    "os.h"
#include    <cstdarg>

Logger::Logger()
    : _cur_day(-1)
    , _enable_verbose(false)
    , _file(nullptr)
    , _buf(new char[65536])
    , _lock() {}

Logger::~Logger() {
    std::unique_lock<std::mutex> _(_lock);
    if (_buf) delete[] _buf;
    if (_file) fclose(_file);
    _file = nullptr;
}

Logger & Logger::Instance() {
	static Logger * g_logger = new Logger;
    return *g_logger;
}

void Logger::Verbose(const char * fmt, ...) {
    if (!_enable_verbose) return;

    va_list args;
    va_start(args, fmt);
    __Write('V', fmt, args);
    va_end(args);
}

void Logger::VerboseV(const char * fmt, va_list args) {
    if (!_enable_verbose) return;
    __Write('V', fmt, args);
}

void Logger::Info(const char * fmt, ...) {
    va_list args;
    va_start(args, fmt);
    __Write('I', fmt, args);
    va_end(args);
}

void Logger::Warn(const char * fmt, ...) {
    va_list args;
    va_start(args, fmt);
    __Write('W', fmt, args);
    va_end(args);
}

void Logger::Error(const char * fmt, ...) {
    va_list args;
    va_start(args, fmt);
    __Write('E', fmt, args);
    va_end(args);
}

void Logger::__Write(char type, const char * fmt, va_list args) {
	std::unique_lock<std::mutex> _(_lock);

    DateTime now;
    
    if (!_file || now.day != _cur_day) {
        _cur_day = now.day;
        
        char path[512] = {0};
        snprintf(path, 512, "logs/omni_%04d-%02d-%02d.log", now.year, now.month, now.day);

        if (!Exists("logs")) MakeDir("logs");
        if (_file) fclose(_file);
        _file = fopen(path, "a+");
    }

    int offset = snprintf(_buf, 65535, "[%04d-%02d-%02d %02d:%02d:%02d.%03d][%c]",
        now.year, now.month, now.day, now.hour, now.minute, now.second, now.millisec, type);
    offset += vsnprintf(_buf + offset, 65535 - offset, fmt, args);

    _buf[offset + 1] = '0';
    printf(_buf);
    printf("\n");

    if (_file) {
        fwrite(_buf, 1, offset, _file);
        fputc('\n', _file);
        fflush(_file);
    }
} 